﻿using System;

using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Silvermoon.Utils
{
    public static class ColorUtil
    {
        /// <summary>
        /// Gets the Color as a result of a background color overlapped by a color with a transparency.
        /// </summary>
        /// <param name="backColor">The background color.</param>
        /// <param name="blendColor">The overlapped color.</param>
        /// <param name="alpha">The alphablend value between 0 and 255.</param>
        /// <returns>A combinded color.</returns>
        public static Color AlphaBlendColor(Color backColor, Color blendColor, int alpha)
        {
            int r = Blend(blendColor.R, backColor.R, alpha);
            int g = Blend(blendColor.G, backColor.G, alpha);
            int b = Blend(blendColor.B, backColor.B, alpha);

            return Color.FromArgb(r, g, b);
        }


        private static int Blend(int value1, int value2, int alpha)
        {
            int d = value1 - value2;
            return (d * alpha) / 255 + value2;
        }

        public static Color[] CreatePlasticColors(Color color)
        {
            Color[] result = new Color[4];
            result[0] = AlphaBlendColor(color, Color.White, 160);
            result[1] = AlphaBlendColor(color, Color.White, 60);
            result[2] = color;
            result[3] = AlphaBlendColor(color, Color.Black, 54);
            return result;
        }

        public static Color[] CreateChromeColors(Color color)
        {
            Color[] result = new Color[4];
            result[0] = AlphaBlendColor(color, Color.White, 140);
            result[1] = AlphaBlendColor(color, Color.White, 32);
            result[2] = color;
            result[3] = AlphaBlendColor(color, Color.Black, 140);
            return result;
        }

        public static Color[] CreateFlatChromeColors(Color color)
        {
            Color[] result = new Color[4];
            result[0] = AlphaBlendColor(color, Color.White, 140);
            result[1] = AlphaBlendColor(color, Color.White, 40);
            result[2] = color;
            result[3] = AlphaBlendColor(color, Color.Black, 64);
            return result;
        }


        public static Color[] CreateGradientColor(Color color)
        {
            Color[] result = new Color[4];
            result[0] = AlphaBlendColor(color, Color.White, 120);
            result[1] = color; // AlphaBlendColor(color, Color.White, 30);
            result[2] = color;
            result[3] = AlphaBlendColor(color, Color.Black, 20);
            return result;
        }


        /// <summary>
        /// Converts a 24 or less bit color to a 32 bit color with a specific alpha channel.
        /// </summary>
        /// <param name="c">The rgb color to convert.</param>
        /// <param name="alpha">The alpha value for the color.</param>
        /// <returns>The new color with alpha channel.</returns>
        public static Color AlphaColor(Color c, int alpha)
        {
            uint ualpha = (uint)alpha;
            ualpha = ualpha << 24;
            int mask = (int)ualpha;
            int v = (c.ToArgb() & 0xFFFFFF) | mask;
            //int v = c.B | (c.G << 8) | (c.R << 0x10) | mask;

            return Color.FromArgb(v);
        }

        /// <summary>
        /// Converts a 24 or less bit color to a 32 bit color with a specific alpha channel and swaps the red and blue values.
        /// </summary>
        /// <param name="c">The rgb color to convert.</param>
        /// <param name="alpha">The alpha value for the color.</param>
        /// <returns>The new color with alpha channel.</returns>
        public static Color AlphaSwapBRColor(Color c, int alpha)
        {
            uint ualpha = (uint)alpha;
            ualpha = ualpha << 24;
            int mask = (int)ualpha;
            int v = c.R | (c.G << 8) | (c.B << 0x10) | mask;

            return Color.FromArgb(v);
        }


        public static Color[] SingleColor(Color color)
        {
            return new Color[] { color };
        }

        /// <summary>
        /// Interpolates a color between two colors.
        /// </summary>
        /// <param name="color">The start color.</param>
        /// <param name="color2">The end color </param>
        /// <param name="proportion">The proportion between color and color2, multiplied with 256.</param>
        /// <returns>The interpolated color.</returns>
        public static Color InterpolateColor(Color color, Color color2, int proportion)
        {
            int r = InterpolateValue(color.R, color2.R, proportion);
            int b = InterpolateValue(color.B, color2.B, proportion);
            int g = InterpolateValue(color.G, color2.G, proportion);
            int a = InterpolateValue(color.A, color2.A, proportion);

            int value = (int)(((ulong)((((r << 0x10) | (g << 8)) | b) | (a << 0x18))) & 0xffffffffL);
            return Color.FromArgb(value);
        }

        private static int InterpolateValue(byte a, byte b, int proportion)
        {
            return a + ((b - a) * proportion) / 256;
        }
    }
}
